package org.xqp.order.service.impl;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xqp.basic.exception.MyException;
import org.xqp.basic.service.impl.BaseServiceImpl;
import org.xqp.basic.util.LoginContextUtil;
import org.xqp.order.domain.OrderAddress;
import org.xqp.order.domain.OrderPet;
import org.xqp.order.domain.OrderPetDetail;
import org.xqp.order.dto.SaveOrderDto;
import org.xqp.order.service.IOrderAddressService;
import org.xqp.order.service.IOrderPetDetailService;
import org.xqp.order.service.IOrderPetService;
import org.xqp.pay.domain.PayBill;
import org.xqp.pay.service.IPayBillService;
import org.xqp.pet.domain.Pet;
import org.xqp.pet.service.IPetService;
import org.xqp.user.domain.Logininfo;
import org.xqp.user.domain.UserAddress;
import org.xqp.user.mapper.UserAddressMapper;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
@Transactional
public class OrderPetServiceImpl extends BaseServiceImpl<OrderPet> implements IOrderPetService {


    @Autowired
    private IPetService petService;

    @Autowired
    private IPayBillService payBillService;

    @Autowired
    private IOrderPetDetailService orderPetDetailService;

    @Autowired
    private UserAddressMapper userAddressMapper ;

    @Autowired
    private IOrderAddressService orderAddressService;

    /**
     * 下单
     * 1.校验参数,
     * 2.查询宠物信息，判断宠物上架
     * 3.查询用户地址，支付方式
     * 4.创建订单号 ，计算支付超时时间，保存订单数据
     * 5.保存订单明细
     * 6.保存订单地址
     * 7.宠物表，库存-1。什么时候扣库存？下单减库存
     * @param dto ：下单参数
     */
    @Override
    public String placeOrder(SaveOrderDto dto) {

        //============================参数判断====================================
        //* 1.校验参数,
        Long addressId = dto.getAddressId();
        Integer payType = dto.getPayType();
        Long petId = dto.getPetId();
        if(null == addressId){
            throw new MyException("无效的地址");
        }
        if(null == payType){
            throw new MyException("无效的支付类型");
        }
        if(null == petId){
            throw new MyException("无效的宠物ID");
        }
        //===============================宠物&地址查询=================================
        //* 2.查询宠物信息，判断宠物上架
        //宠物类型，宠物店铺 JOIN 一起查询
        Pet pet = null;

        //判断库存
        //===========================扣减宠物库存=====================================
        //* 7.宠物表，库存-1。什么时候扣库存？下单减库存
        synchronized (this){//防止超卖，上锁
            pet = petService.selectOnLineById(petId); // 根据宠物id去查询宠物并且宠物状态要上架
            if(null == pet){
                throw new MyException("无效的宠物");
            }
            //线程
            if(pet.getStore_number() == null || pet.getStore_number().intValue() == 0){
                throw new MyException("货存不足");
            }
            pet.setStore_number(pet.getStore_number()-1);
            petService.update(pet);
        }

        //* 3.查询用户地址，支付方式
        UserAddress userAddress = userAddressMapper.selectById(addressId);
        if(null == userAddress){
            throw new MyException("无效的地址");
        }

        //==========================构建&保存订单======================================
        //* 4.创建订单号 ，
        String orderNo = UUID.randomUUID().toString().replaceAll("-","" ); // 通过uuid创建的字符串中间有根—将数字连接起来，看起来不好看所以我们用替换方法把—去掉
        Date now = new Date();
        // 计算支付超时时间，保存订单数据
        //TODO :测试使用 30s,记得修改
        Date payExpireTime = DateUtils.addSeconds(now, 30); // 获取当前时间加上30秒的时间
        //保存订单
        OrderPet orderPet = new OrderPet();
        //摘要
        orderPet.setDigest("购买："+pet.getName()+"下单");
        orderPet.setCreateTime(now);
        //支付超时时间
        orderPet.setPayExpireTime(payExpireTime);
        //订单号
        orderPet.setOrderSn(orderNo);
        orderPet.setPayType(payType);
        //状态:待支付
        orderPet.setState(OrderPet.STATE_WAIT_PAY);
        orderPet.setTotalCount(1);
        //金额+邮费  创建一个BigDecimal后面用字符串，用数字的话精度不够高只是无限接近该数字，
        orderPet.setTotalPrice(pet.getSaleprice().add(new BigDecimal("10")));
        //获取登录用户
        Logininfo loginContext = LoginContextUtil.getLoginContext();
        if(loginContext == null){
            throw new MyException("请登录");
        }
        orderPet.setUserId(loginContext.getId());
        //保存订单  将订单保存到数据库
        super.insert(orderPet);
        //==========================构建&保存订单明细======================================
        //* 5.保存订单明细
        OrderPetDetail detail = new OrderPetDetail();
        detail.setCount(1);
        detail.setCreatetime(now);
        //宠物名
        detail.setName(pet.getName());
        //订单
        detail.setOrderId(orderPet.getId());
        detail.setOrderSn(orderNo);
        detail.setPetId(pet.getId());
        //价格
        detail.setPrice(pet.getSaleprice());
        //图片
        detail.setResources(pet.getResources());
        //店铺
        detail.setShopId(pet.getShop().getId());
        detail.setShopName(pet.getShop().getName());
        // 将订单明细保存到数据库
        orderPetDetailService.insert(detail);

        //===========================构建保存订单地址=====================================
        //* 6.保存订单地址
        OrderAddress orderAddress = new OrderAddress();
        //属性拷贝
        BeanUtils.copyProperties(userAddress, orderAddress);
        orderAddress.setOrderId(orderPet.getId());
        orderAddress.setOrderSn(orderNo);
        orderAddress.setCreateTime(now);
        // 将订单地址保存到数据库
        orderAddressService.insert(orderAddress);

        //========================================保存一个支付单==============================
        payBillService.save(
                orderPet.getId(),   //外键
                PayBill.BUSINESS_TYPE_PET, //业务类型
                "购买："+pet.getName()+"，支付："+orderPet.getTotalPrice(),
                orderPet.getTotalPrice(), //总价格
                dto.getPayType(),//支付方式用户选的
                pet.getShop().getId() ,//店铺id
                pet.getShop().getName(), // 店铺名字
                orderPet.getOrderSn()); //订单单号
        // 返回订单号给前端，前端通过订单号等条件给支付宝发起支付请求
        return orderNo;
        //========================================保存订单超时定时任务==============================
        //ctrl + home  ; ctrl + end
        //String jobName,Class cls,Object params, Date excuteTime
//        Map<String,String> dataMap = new HashMap<>();
//        dataMap.put("orderNo",orderNo );
//        String jobName = "orderExpireJob:"+orderNo;
//        dataMap.put("jobName",jobName );
//
//        quartzService.addOrderExpireJob(
//                jobName,//定时任务名字
//                cn.itsource.quartz.job.OrderExpireJob.class,//订单超时处理工作类
//                dataMap,    //数据
//                payExpireTime);//执行时间
//
//        //返回订单号
    }
}
